//
// Author: zxc
// Date: 2021/4/7
// Copyright (c) 2021 zxc All rights reserved.
//
// 简单实现一个brainfuck语言的解释器
//

#include <iostream>
#include <string>
#include <stack>

using std::cout;
using std::endl;
using std::string;
using std::stack;

int main(int argc, char** argv)
{
    // Hello World!
    static string input = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.";

    char data[3000]{0};
    stack<int> fp_stack;
    // 程序指针
    int fp = 0;
    // 数组指针
    int p = 0;
    // 临时指针
    int tp = 0;
    // 匹配
    bool match = false;

    while(fp != input.size())
    {
        char opCode = input[fp];
        switch (opCode)
        {
            case '+':
                ++data[p];
                ++fp;
                break;
            case '-':
                --data[p];
                ++fp;
                break;
            case '[':
                if(data[p] == 0)
                {
                    tp = fp + 1;
                    fp_stack.push(fp);
                    while (tp != input.size())
                    {
                        if(input[tp] == '[')
                        {
                            fp_stack.push(tp);
                        }
                        else if(input[tp] == ']')
                        {
                            if(fp_stack.top() == fp)
                            {
                                match = true;
                                fp_stack.pop();
                                fp = tp + 1;
                                break;
                            }
                            else
                            {
                                fp_stack.pop();
                            }
                        }
                        ++tp;
                    }
                    if(!match)
                    {
                        cout << "No ] matches [ at "<< fp << endl;
                        return -1;
                    }
                }
                else
                {
                    ++fp;
                }
                break;
            case ']':
                tp = fp - 1;
                fp_stack.push(fp);
                match = false;
                while (tp != -1)
                {
                    if(input[tp] == ']')
                    {
                        fp_stack.push(tp);
                    }
                    else if(input[tp] == '[')
                    {
                        if(fp_stack.top() == fp)
                        {
                            match = true;
                            fp_stack.pop();
                            fp = tp;
                            break;
                        }
                        else
                        {
                            fp_stack.pop();
                        }
                    }
                    --tp;
                }
                if(!match)
                {
                    cout << "No [ matches ] at "<< fp << endl;
                    return -1;
                }
                break;
            case '>':
                ++p;
                ++fp;
                break;
            case '<':
                --p;
                ++fp;
                break;
            case '.':
                cout << data[p];
                ++fp;
                break;
            default:
                ++fp;
                break;
        }
    }

    cout << endl;

    return 0;
}

